#pragma once
#ifndef _fastbird_RenderStructs_header_included_
#define _fastbird_RenderStructs_header_included_
#include <Engine/Renderer/RendererEnums.h>
#include <string>

namespace fastbird
{
	struct RASTERIZER_DESC
	{
		RASTERIZER_DESC()
			: FillMode(FILL_MODE_SOLID)
			, CullMode(CULL_MODE_BACK)
			, FrontCounterClockwise(false)
			, DepthBias(0)
			, DepthBiasClamp(0.f)
			, SlopeScaledDepthBias(0.f)
			, DepthClipEnable(true)
			, ScissorEnable(false)
			, MultisampleEnable(true)
			, AntialiasedLineEnable(true)
		{
		}

		bool operator<(const RASTERIZER_DESC& other) const
		{
			if (memcmp(this, &other, sizeof(RASTERIZER_DESC)) < 0)
				return true;
			
			return false;
		}

		FILL_MODE		FillMode;
		CULL_MODE		CullMode;
		bool            FrontCounterClockwise;
		int             DepthBias;
		float           DepthBiasClamp;
		float           SlopeScaledDepthBias;
		bool            DepthClipEnable;
		bool            ScissorEnable;
		bool            MultisampleEnable;
		bool            AntialiasedLineEnable;
	};

	struct SAMPLER_DESC
	{
		SAMPLER_DESC()
			: Filter(TEXTURE_FILTER_MIN_MAG_MIP_LINEAR)
			, AddressU(TEXTURE_ADDRESS_CLAMP)
			, AddressV(TEXTURE_ADDRESS_CLAMP)
			, AddressW(TEXTURE_ADDRESS_CLAMP)
			, MipLODBias(0.f)
			, MaxAnisotropy(16)
			, ComparisonFunc(COMPARISON_ALWAYS)
			, MinLOD(-FLT_MAX)
			, MaxLOD(FLT_MAX)

		{
			BorderColor[0] = BorderColor[1] = BorderColor[2] = BorderColor[3] = 0.f;
		}

		bool operator<(const SAMPLER_DESC& other) const
		{
			if (memcmp(this, &other, sizeof(SAMPLER_DESC)) < 0)
				return true;
			
			return false;
		}

		TEXTURE_FILTER       Filter;
		TEXTURE_ADDRESS_MODE AddressU;
		TEXTURE_ADDRESS_MODE AddressV;
		TEXTURE_ADDRESS_MODE AddressW;
		float                MipLODBias;
		unsigned int         MaxAnisotropy;
		COMPARISON_FUNC      ComparisonFunc;
		float                BorderColor[4];
		float                MinLOD;
		float                MaxLOD;
	};

	struct RENDER_TARGET_BLEND_DESC
	{
		bool			BlendEnable;
		BLEND			SrcBlend;
		BLEND			DestBlend;
		BLEND_OP		BlendOp;
		BLEND			SrcBlendAlpha;
		BLEND			DestBlendAlpha;
		BLEND_OP		BlendOpAlpha;
		unsigned char	RenderTargetWriteMask;
	};

	struct BLEND_DESC
	{
		BLEND_DESC()
			:AlphaToCoverageEnable(false)
			, IndependentBlendEnable(false)
		{
			for (int i=0; i<8; i++)
			{
				RenderTarget[i].BlendEnable = false;
				RenderTarget[i].SrcBlend = BLEND_ONE;
				RenderTarget[i].DestBlend = BLEND_ZERO;
				RenderTarget[i].BlendOp = BLEND_OP_ADD;
				RenderTarget[i].SrcBlendAlpha = BLEND_ONE;
				RenderTarget[i].DestBlendAlpha = BLEND_ZERO;
				RenderTarget[i].BlendOpAlpha = BLEND_OP_ADD;
				RenderTarget[i].RenderTargetWriteMask = COLOR_WRITE_ENABLE_ALL;
			}
		}

		bool operator<(const BLEND_DESC& other) const
		{
			if (memcmp(this, &other, sizeof(BLEND_DESC)) < 0)
				return true;
			
			return false;
		}

		bool						AlphaToCoverageEnable;
		bool						IndependentBlendEnable;
		RENDER_TARGET_BLEND_DESC	RenderTarget[8];
	};

	struct RENDERER_FRAME_PROFILER
	{
		RENDERER_FRAME_PROFILER()
		{
			FrameRate = 30;
			FrameRateDisplay = 30;
			FrameRateDisplayUpdateTime = 0.0f;
		}
		void Clear()
		{
			NumDrawCall = 0;
			NumVertexCount = 0;

			NumDrawIndexedCall = 0;
			NumIndexCount = 0;
		}

		void UpdateFrameRate(float dt)
		{
			FrameRateDisplayUpdateTime += dt;
			FrameRate = (FrameRate + 1.0f/dt)/2.0f;
			if (FrameRateDisplayUpdateTime>0.5f)
			{
				FrameRateDisplayUpdateTime = 0.f;
				FrameRateDisplay = FrameRate;
			}

		}

		unsigned int NumDrawCall;
		unsigned int NumVertexCount;
		
		unsigned int NumDrawIndexedCall;
		unsigned int NumIndexCount;

		float FrameRate;
		float FrameRateDisplay;
		float FrameRateDisplayUpdateTime;
	};

	struct INPUT_ELEMENT_DESC
	{
		std::string mSemanticName;
		unsigned mSemanticIndex;
		INPUT_ELEMENT_FORMAT mFormat;
		unsigned mInputSlot;
		unsigned mAlignedByteOffset;
		INPUT_CLASSIFICATION mInputSlotClass;
		unsigned mInstanceDataStepRate;
	};
}

#endif //_fastbird_RenderStructs_header_included_